﻿using System;
using System.Collections.Generic;
using System.Text;
using System.Security.Cryptography;

namespace libAsymmetricEncryption
{
    public class RSA_KeyManager
    {
        public static int KEY_SIZE = 1024;

        private static RSA_KeyManager _instance = null;

        public static RSA_KeyManager getInstance()
        {
            if (_instance == null)
            {
                _instance = new RSA_KeyManager();
            }

            return _instance;
        }

        private RSA_Key _serverPublicKey;

        public RSA_Key ServerPublicKey
        {
            get { return _serverPublicKey; }
            set { _serverPublicKey = value; }
        }

        private RSA_Key _serverPrivateKey;

        public RSA_Key ServerPrivateKey
        {
            get { return _serverPrivateKey; }
            set { _serverPrivateKey = value; }
        }

        public void initServerKeys()
        {
            GenerateKey(KEY_SIZE);
        }
        
        private void GenerateKey(int sizeOfKey)
        {
            const int PROVIDER_RSA_FULL = 1;
            CspParameters cp = new CspParameters(PROVIDER_RSA_FULL);
            cp.KeyContainerName = this.RandomString();
            cp.Flags = CspProviderFlags.UseMachineKeyStore;
            cp.ProviderName = "Microsoft Strong Cryptographic Provider";

            RSACryptoServiceProvider rsa = new RSACryptoServiceProvider(sizeOfKey, cp);

            byte[] modulus = rsa.ExportParameters(false).Modulus;
            byte[] exponent = rsa.ExportParameters(false).Exponent;
            byte[] d = rsa.ExportParameters(true).D;

            RSAParameters publicParameters = rsa.ExportParameters(false);
            privateParameters = rsa.ExportParameters(true);

            _serverPrivateKey = new RSA_Key(modulus, d);
            _serverPublicKey = new RSA_Key(modulus, exponent);
        }

        public RSAParameters privateParameters;

        private string RandomString()
        {
            Random r = this.getRandomGenerater();

            StringBuilder sb = new StringBuilder();
            int len = r.Next(5, 20);

            for (int i = 0; i < len; i++)
            {
                int k1 = r.Next(0, 1);                  //0 --> 9
                int k2 = (k1 == 0) ? r.Next(0, 1) : 0;     //A --> Z
                int k3 = (k1 + k2 == 0) ? 1 : 0;          //a --> b
                int j = r.Next(48, 57) * k1 + r.Next(65, 90) * k2 + r.Next(97, 122) * k3;
                sb.Append(Convert.ToChar(j));
            }

            return sb.ToString();
        }

        private  int first = 1;

        private  Random r;

        private Random getRandomGenerater()
        {
            if (first == 1 && r == null)
            {
                r = new Random(System.DateTime.Today.Minute * System.DateTime.Today.Millisecond);
            }

            return r;
        }

    }
}
